package com.toommi.refuse.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.toommi.refuse.common.enums.CommonStatusEnum;
import com.toommi.refuse.common.enums.RedisKeyEnum;
import com.toommi.refuse.common.util.DateUtil;
import com.toommi.refuse.common.util.GsonUtil;
import com.toommi.refuse.entity.AppUser;
import com.toommi.refuse.entity.Constant;
import com.toommi.refuse.entity.TextMessage;
import com.toommi.refuse.enums.AppUserExceptionEnum;
import com.toommi.refuse.exception.AppUserException;
import com.toommi.refuse.mapper.AppUserMapper;
import com.toommi.refuse.mapper.LargeAppointmeMapper;
import com.toommi.refuse.model.AppLoginModel;
import com.toommi.refuse.model.AppUserModel;
import com.toommi.refuse.service.AppUserService;
import com.toommi.refuse.service.RedisService;
import com.toommi.refuse.tools.Md5Util;
import com.toommi.refuse.tools.MessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yangg
 * @since 2019-07-23 16:14
 */
@Service
@Slf4j
public class AppUserServiceImpl implements AppUserService {

    @Resource
    private AppUserMapper appUserMapper;
    @Resource
    private LargeAppointmeMapper appointmeMapper;

    @Resource
    private RedisService redisService;
    //小程序APPid
    // private final static String appid = "wx51cadd4d75f054a3";
    private final static String appid = "wx315001e7fa28b8ac";
    //private final static String secret = "0362692877edb054f97bbc042d00f937";
    private final static String secret = "8880832e697b5676b5ec94436e276375";
    //小程序回收APPid
    private final static String hsappid = "wx3ba11d0cbb98c476";
    private final static String hssecret = "6141ee99666c016d634b967308fa5b96";

    @Override
    public PageInfo<AppUserModel> getUsers(int pageSize, int currentPage, String keyWord) {

        PageHelper.startPage(currentPage, pageSize);
        List<AppUser> appUsersList = appUserMapper.selectAll();
        List<AppUserModel> appUserModels = new ArrayList<>(appUsersList.size());
        for (AppUser appUser : appUsersList) {
            AppUserModel userModel = new AppUserModel();
            BeanUtils.copyProperties(appUser, userModel);
            userModel.setPassword("");
            appUserModels.add(userModel);
        }
        return new PageInfo<>(appUserModels);
    }

    @Override
    public void saveUser(AppUserModel appUserModel) throws AppUserException {
        //基础数据校验
        checkBasicUserModel(appUserModel);

        AppUser appUser = new AppUser();
        if (appUserModel.getId() <= 0) {
            checkNewUserModel(appUserModel);
            //新增用户
            BeanUtils.copyProperties(appUserModel, appUser);
            //密码加密
            appUser.setCreateTime(System.currentTimeMillis());
            appUser.setUpdateTime(System.currentTimeMillis());
            appUser.setStatus(CommonStatusEnum.NORMAL.getCode());
            appUser.setPassword(Md5Util.encrypt(appUserModel.getPassword()));
            appUserMapper.insert(appUser);
        }
    }

    @Override
    public void updateUser(AppUserModel appUserModel) throws AppUserException {
        //修改信息
        AppUser appUser = appUserMapper.selectByPrimaryKey(appUserModel.getId());
        if (appUser == null) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_USER_NULL);
        }
        appUser.setUpdateTime(System.currentTimeMillis());
        appUser.setStatus(appUserModel.getStatus());
        appUser.setPhone(appUserModel.getPhone());

        appUserMapper.updateByPrimaryKey(appUser);
    }

    @Override
    public void deleteUser(long id) throws AppUserException {

        AppUser appUser = appUserMapper.selectByPrimaryKey(id);
        if (appUser == null) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_USER_NULL);
        }
        appUser.setStatus(CommonStatusEnum.DELETED.getCode());

        appUserMapper.updateByPrimaryKey(appUser);

    }

    @Override
    public AppLoginModel login(AppUserModel appUserModel) throws AppUserException {

        if (StringUtils.isEmpty(appUserModel.getName())) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_USERNAME_NULL);
        }
        if (StringUtils.isEmpty(appUserModel.getPassword())) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_PASSWORD_NULL);
        }

        AppUser example = new AppUser();
        example.setName(appUserModel.getName());
        example.setPassword(Md5Util.encrypt(appUserModel.getPassword()));
        AppUser loginUser = appUserMapper.selectOne(example);
        if (loginUser == null) {
            //再匹配手机号查找
            AppUser example2 = new AppUser();
            example2.setPhone(appUserModel.getName());
            example2.setPassword(Md5Util.encrypt(appUserModel.getPassword()));
            loginUser = appUserMapper.selectOne(example2);
        }
        if (loginUser == null) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_NAME_PASSWORD);
        }
        //用户状态校验
        if (loginUser.getStatus() != CommonStatusEnum.NORMAL.getCode()) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_USER_LOCKED);
        }
        //生成登录凭据身份标识
        String token = UUID.randomUUID().toString();
        redisService.set(RedisKeyEnum.APP_LOGIN.getKey() + token, GsonUtil.toJson(loginUser));

        AppLoginModel loginModel = new AppLoginModel();

        loginModel.setToken(token);
        loginModel.setAppUserId(loginUser.getId());
        loginModel.setAppUserName(loginUser.getName());
        loginModel.setAppUserPhone(loginUser.getPhone());

        return loginModel;
    }

    /**
     * 获取小区列表
     *
     * @param pageSize
     * @param pageNum
     * @param name
     * @return
     */
    @Override
    public Object getxqlist(String name, int pageSize, int pageNum) throws AppUserException {


        PageHelper.startPage(pageNum, pageSize);
        List<Map<String, Object>> appUsersList = appUserMapper.getxqlist(name);
//        List<AppUserModel> appUserModels = new ArrayList<>(appUsersList.size());
//        for (AppUser appUser : appUsersList) {
//            AppUserModel userModel = new AppUserModel();
//            BeanUtils.copyProperties(appUser, userModel);
//            userModel.setPassword("");
//            appUserModels.add(userModel);
//        }
        return new PageInfo<>(appUsersList).getList();

    }


    /**
     * 校验用户信息数据格式
     *
     * @param userModel 用户信息
     */
    private void checkBasicUserModel(AppUserModel userModel) throws AppUserException {
        //校验用户名格式
        if (StringUtils.isEmpty(userModel.getName()) || userModel.getName().length() > 10) {
            throw new AppUserException(AppUserExceptionEnum.INVlLID_USERNAME_FORMAT);
        }
        //校验密码格式
        if (StringUtils.isEmpty(userModel.getPassword()) || userModel.getPassword().length() > 10) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_PASSWORD_FORMAT);
        }
        //校验手机号不能为空
        if (StringUtils.isEmpty(userModel.getPhone())) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_PHONE_NULL);
        }
    }

    /**
     * 校验新增用户信息数据格式
     *
     * @param userModel 新增用户信息
     */
    private void checkNewUserModel(AppUserModel userModel) throws AppUserException {

        //校验用户名是否已被使用
        AppUser appUser = new AppUser();
        appUser.setName(userModel.getName());
        int count = appUserMapper.selectCount(appUser);
        if (count > 0) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_USERNAME_REPEAT);
        }
        //校验手机号是否已被使用
        AppUser appUser2 = new AppUser();
        appUser2.setPhone(userModel.getPhone());
        int count2 = appUserMapper.selectCount(appUser2);
        if (count2 > 0) {
            throw new AppUserException(AppUserExceptionEnum.INVALID_PHONE_REPEAT);
        }
    }

    @Override
    public String push_Message(HttpServletRequest request, HttpServletResponse response) {
        String respMessage = "";
        String respContent = "";
        try {
            log.info("----------------xml请求解析 ---------------");
            // xml请求解析
            Map<String, String> requestMap = MessageUtil.parseXml(request);
            // 发送方帐号（open_id）
            String fromUserName = requestMap.get("FromUserName");
            log.info("发送方帐号 fromUserName " + fromUserName);
            // 得到全局的 access_token
            // 先判断token是否已经过期如果过期在重新请求
            // 公众帐号
            String toUserName = requestMap.get("ToUserName");
            log.info("公众帐号 toUserName " + toUserName);

            // 消息类型
            String msgType = requestMap.get("MsgType");
            log.info("消息类型   msgType " + msgType);

            // 消息类容
            String content = requestMap.get("Content");
            log.info("消息类容content " + content);

            // 获取二维码的Ticket值
            String QRCode_ticketVlue = requestMap.get("Ticket");
            log.info("获取二维码的Ticket值 " + QRCode_ticketVlue);


            // 事件处理
            if (msgType.equals(Constant.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件类型
                String eventType = requestMap.get("Event");
                log.info("事件类型eventType " + eventType);

                // 关注
                if (eventType.equals(Constant.EVENT_TYPE_SUBSCRIBE)) {
                    log.info("------------------------------------------");
                    log.info("事件类型为关注");
                    //根据fromUserName判断数据库是否存在，如果已经存在，如果不存在就直接添加
                    Map<String, Object> map = appUserMapper.getUserInfoByOpenId(fromUserName);
                    if (map == null) {
                        //直接吧数据添加进去
                        // appUserMapper.insertUserInfo(fromUserName);
                    }

                    // 得到用户详细信息
//					Map<String, Object> result = new HashMap<String,Object>();
//							//obtainUser_DetailedInformation(accesstoken, fromUserName);
//					String nickname = (String) result.get("nickname");
//					LOGGER.info("关注授权获取用户名---------- " + nickname);
//					// 获取当前的用户信息
//					String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\n|\r|\t";
//					Pattern p = Pattern.compile(regEx);
//					Matcher m = p.matcher(nickname);
//					LOGGER.info("关注授权获取用户名是否是特殊字符---------- " + m.find());
//					if (m.find()) {
//
//						nickname=nickname.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "");
//						LOGGER.info("关注授权获取用户名是否是特殊字符过滤之后的字符---------- " + nickname);
//					}else{
//						nickname=nickname.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "");
//						LOGGER.info("非特殊关注授权获取用户名是否是特殊字符过滤之后的字符---------- " + nickname);
//					}

                    // 得到用户性别
//					Integer sex = (Integer) result.get("sex");
//					LOGGER.info("用户性别 sex " + sex);
//					// 得到用户头像
//					String headimgurl = (String) result.get("headimgurl");
//					LOGGER.info("用户头像 headimgurl " + headimgurl);
//					// 用户关注时间
//					Integer subscribe_time = (Integer) result.get("subscribe_time");
//					LOGGER.info("用户关注时间 subscribe_time " + subscribe_time);

//					LOGGER.info("------------------------------------------");
//					LOGGER.info("实例化textMsg对象");
//
                    TextMessage textMessage = new TextMessage();
                    textMessage.setToUserName(fromUserName);
                    textMessage.setFromUserName(toUserName);
                    textMessage.setCreateTime(new Date().getTime());
                    textMessage.setMsgType(Constant.RESP_MESSAGE_TYPE_TEXT);
                    textMessage.setFuncFlag(0);
//
//					LOGGER.info("A textMessage.tosing " + textMessage.toString());
//					LOGGER.info("------------------------------------------");
//					LOGGER.info("判断消息类型");

                    // 查看数据库是否存在该用户
//					Integer count = 0;
                    //userDao.selectUserCont(fromUserName);
//					LOGGER.info("用户是否存在 count " + count);
                    // 添加用户信息
//					String pr_codePath = addUser(count, QRCode_ticketVlue, fromUserName, nickname, sex, headimgurl,
//							subscribe_time, request, response);
//					StringBuffer contentMsg = new StringBuffer();
//					contentMsg.append("欢迎来到办卡街").append("\n\n");
//					contentMsg.append("办卡街公众号为您提供专属服务，开启您的精彩之旅").append("\n");
//					// contentMsg.append("客服服务时间8:30到20:30，全年无休，客服电话：023-86687541").append("\n");
//					respContent = contentMsg.toString();
//					LOGGER.info("B textMessage.tosting " + textMessage.toString());
//					LOGGER.info("respContent");
//					LOGGER.info("------------------------------------------");
                    textMessage.setContent("垃圾分一分，城市美十分。欢迎关注互联网垃圾分类信息管理平台！");
//					LOGGER.info("C textMessage.tosting " + textMessage.toString());
                    respMessage = MessageUtil.textMessageToXml(textMessage);

                }

                log.info("字符串respMessage " + respMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.info("service respMessage " + respMessage);
        return respMessage;
    }


    /**
     * @seeget请求类
     */
    public String startAlipayGet(String url, Map<String, String> params) throws Exception {
        // Post请求的url，与get不同的是不需要带参数
        URL postUrl = new URL(url);
        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();
        // 设置是否向connection输出，因为这个是post请求，参数要放在
        // http正文内，因此需要设为true
        connection.setDoOutput(true);
        // Read from the connection. Default is true.
        connection.setDoInput(true);
        // 默认是 GET方式
        connection.setRequestMethod("GET");
        // Post 请求不能使用缓存
        connection.setUseCaches(false);
        connection.setConnectTimeout(4000);
        connection.setReadTimeout(7000);
        // 设置本次连接是否自动重定向
        connection.setInstanceFollowRedirects(true);
        // 配置本次连接的Content-type，配置为application/x-www-form-urlencoded的
        // 意思是正文是urlencoded编码过的form参数
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        // 连接，从postUrl.openConnection()至此的配置必须要在connect之前完成，
        // 要注意的是connection.getOutputStream会隐含的进行connect。
        connection.connect();
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        // 正文，正文内容其实跟get的URL中 '? '后的参数字符串一致
//		String content = postParams(params);
        // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写到流里面
//		out.write(content.getBytes("UTF-8"));
        // 流用完记得关
//		out.flush();
//		out.close();
        // 获取响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
        String line;
        StringBuffer result = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
            result.append(line);
        }
        reader.close();
        // 该干的都干完了,记得把连接断了
        connection.disconnect();
        log.info("返回值-----------------" + result.toString());
        return result.toString();
    }

    public String postParams(Map<String, String> params) throws IOException {
        StringBuilder outBuf = new StringBuilder();
        boolean isNotFirst = false;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (isNotFirst) {
                outBuf.append('&');
            }
            isNotFirst = true;
            // 参数需要转码
            outBuf.append(entry.getKey()).append('=').append(entry.getValue());
        }
        // 做转译
        return outBuf.toString();
    }

    @Override
    public Object CommonResponse(HttpServletRequest request) throws AppUserException {
        try {
            Map<String, Object> result = new HashMap<String, Object>();
            String code = request.getParameter("code");
            if (StringUtil.isEmpty(code)) {
                throw new AppUserException(AppUserExceptionEnum.INVALID_PHONE_NULL);
            }
            Integer status = 0;//0表示已授权已绑定，1表示已授权未绑定，2表示已经授权未审核或者审核未成功
            Map<String, String> params = new HashMap<String, String>();
            String json = startAlipayGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code", params);
            //解析json数据
            JSONObject obejct = JSONObject.parseObject(json);
            String openid = obejct.getString("openid");
            //根据openid去查询用户表是否存在这个openid，如果存在判断是否已经绑定了
            Map<String, Object> qjguser = appUserMapper.getUserInfoByOpenId(openid);
            result.put("openid", openid);
            if (qjguser == null) {
                //还没有授权过，添加到数据，需要页面跳转到绑定页面
                appUserMapper.insertUserInfo(result);
                status = 1;
            } else {
                //判断是否已经绑定了信息
                String code_qjg = String.valueOf(qjguser.get("code"));
                String id = String.valueOf(qjguser.get("id"));
                result.put("id", id);
                if (StringUtil.isEmpty(code_qjg)) {
                    //表示还没有绑定，跳到绑定y页面
                    status = 1;
                } else {
                    //判断是否已经审核
//					String status1=String.valueOf(qjguser.get("status"));
//					if(!"1".equals(status1)){
//						status=2;
//					}
                }
            }
            result.put("status", status);
            return result;
        } catch (Exception e) {
            log.info("小程序授权失败");
            return null;
        }
    }

    /**
     * 会手段授权
     *
     * @param request
     * @throws AppUserException
     */
    @Override
    public Object hssq(HttpServletRequest request) throws AppUserException {
        try {
            Map<String, Object> result = new HashMap<String, Object>();
            String code = request.getParameter("code");
            if (StringUtil.isEmpty(code)) {
                throw new AppUserException(AppUserExceptionEnum.INVALID_PHONE_NULL);
            }
            //0表示已授权待审核，1表示已授权审核通过，2表示已经授权未审核或者审核未成功
            Integer status = null;
            String id = null;
            Map<String, String> params = new HashMap<String, String>();
            String json = startAlipayGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + hsappid + "&secret=" + hssecret + "&js_code=" + code + "&grant_type=authorization_code", params);
            //解析json数据
            JSONObject obejct = JSONObject.parseObject(json);
            String openid = obejct.getString("openid");
            //根据openid去查询用户表是否存在这个openid，如果存在判断是否已经绑定了
            Map<String, Object> qjguser = appUserMapper.getAPPUserInfoByOpenId(openid);
            result.put("openid", openid);
            AppUser appUser = new AppUser();
            if (qjguser == null) {
                //还没有授权过，添加数据，需要页面跳转到绑定(注册)页面
                appUser.setOpenid(openid);
                //状态：0-审核中；1-审核成功；2-审核失败；9-已授权
                appUser.setStatus(9);
                appUser.setCreateTime(System.currentTimeMillis());
                appUserMapper.insertAPPUser(appUser);
                //同时新增该用户的支付信息
                Map<String, Object> param = new HashMap<>();
                String date = DateUtil.formatTimestampToString(System.currentTimeMillis(), DateUtil.DATE_FORMATE_YM);
                param.put("app_user_id", appUser.getId());
                param.put("date", date);
                param.put("money", 0);
                appointmeMapper.insertMoney(param);

                id = String.valueOf(appUser.getId());
                status = 9;
            } else {
                //状态：0-审核中；1-审核成功；2-审核失败；9-已授权
                  /*   String sstatus = String.valueOf(qjguser.get("status"));
           //根据用户状态返回前端所需状态码：0-已注册；1-未注册；2-未审核、审核未通过
                if ("9".equals(sstatus)) {
                    status = 1;
                } else if ("1".equals(sstatus)) {
                    status = 0;
                } else {
                    status = 2;
                }
*/
                id = String.valueOf(qjguser.get("id"));
                status = (Integer) qjguser.get("status");
            }
            result.put("id", id);
            result.put("status", status);
            return result;
        } catch (Exception e) {
            log.info("小程序授权失败");
            return null;
        }
    }
}

